"""
五子棋棋盘类
负责管理棋盘状态、落子、胜负判断等核心逻辑
"""

import numpy as np
from config import BOARD_SIZE, WIN_COUNT


class Board:
    """五子棋棋盘类"""
    
    def __init__(self, size=BOARD_SIZE):
        """
        初始化棋盘
        
        Args:
            size: 棋盘大小（默认15x15）
        """
        self.size = size
        self.board = np.zeros((size, size), dtype=int)
        self.last_move = None  # 记录最后一步落子位置
        self.move_history = []  # 记录所有落子历史
    
    def copy(self):
        """
        复制棋盘状态
        
        Returns:
            numpy.ndarray: 棋盘副本
        """
        return self.board.copy()
    
    def make_move(self, row, col, player):
        """
        在指定位置落子
        
        Args:
            row: 行坐标
            col: 列坐标
            player: 玩家标识（1或-1）
        
        Returns:
            bool: 是否落子成功
        """
        if self.is_valid_move(row, col):
            self.board[row, col] = player
            self.last_move = (row, col)
            self.move_history.append((row, col, player))
            return True
        return False
    
    def is_valid_move(self, row, col):
        """
        检查落子是否合法
        
        Args:
            row: 行坐标
            col: 列坐标
        
        Returns:
            bool: 是否为合法落子
        """
        return (0 <= row < self.size and 
                0 <= col < self.size and 
                self.board[row, col] == 0)
    
    def check_winner(self):
        """
        检查是否有玩家获胜
        
        Returns:
            int: 1（黑方胜）、-1（白方胜）、0（未结束）
        """
        # 四个方向：横、竖、主对角线、副对角线
        directions = [(0, 1), (1, 0), (1, 1), (1, -1)]
        
        for i in range(self.size):
            for j in range(self.size):
                if self.board[i][j] == 0:
                    continue
                
                player = self.board[i][j]
                
                # 检查四个方向
                for dx, dy in directions:
                    count = 1
                    
                    # 正方向计数
                    x, y = i + dx, j + dy
                    while (0 <= x < self.size and 0 <= y < self.size 
                           and self.board[x][y] == player):
                        count += 1
                        x += dx
                        y += dy
                    
                    # 反方向计数
                    x, y = i - dx, j - dy
                    while (0 <= x < self.size and 0 <= y < self.size 
                           and self.board[x][y] == player):
                        count += 1
                        x -= dx
                        y -= dy
                    
                    # 检查是否达到获胜条件
                    if count >= WIN_COUNT:
                        return player
        
        return 0
    
    def is_full(self):
        """
        检查棋盘是否已满
        
        Returns:
            bool: 棋盘是否已满
        """
        return not np.any(self.board == 0)
    
    def get_empty_positions(self):
        """
        获取所有空位置
        
        Returns:
            list: 空位置列表 [(row, col), ...]
        """
        positions = []
        for i in range(self.size):
            for j in range(self.size):
                if self.board[i][j] == 0:
                    positions.append((i, j))
        return positions
    
    def has_neighbor(self, row, col, distance=2):
        """
        检查指定位置周围是否有棋子
        
        Args:
            row: 行坐标
            col: 列坐标
            distance: 搜索距离
        
        Returns:
            bool: 周围是否有棋子
        """
        for i in range(max(0, row - distance), 
                      min(self.size, row + distance + 1)):
            for j in range(max(0, col - distance), 
                          min(self.size, col + distance + 1)):
                if self.board[i][j] != 0:
                    return True
        return False
    
    def get_legal_moves(self, distance=2):
        """
        获取所有合法落子位置（优化版：只考虑已有棋子周围）
        
        Args:
            distance: 搜索距离
        
        Returns:
            list: 合法落子位置列表
        """
        moves = []
        
        # 如果棋盘为空，返回中心位置
        if np.all(self.board == 0):
            center = self.size // 2
            return [(center, center)]
        
        # 只考虑已有棋子周围的位置
        for i in range(self.size):
            for j in range(self.size):
                if self.board[i][j] == 0 and self.has_neighbor(i, j, distance):
                    moves.append((i, j))
        
        return moves if moves else self.get_empty_positions()
    
    def reset(self):
        """重置棋盘到初始状态"""
        self.board = np.zeros((self.size, self.size), dtype=int)
        self.last_move = None
        self.move_history = []
    
    def undo_move(self):
        """
        悔棋（撤销最后一步）
        
        Returns:
            bool: 是否成功悔棋
        """
        if self.move_history:
            row, col, _ = self.move_history.pop()
            self.board[row, col] = 0
            
            # 更新last_move
            if self.move_history:
                self.last_move = (self.move_history[-1][0], self.move_history[-1][1])
            else:
                self.last_move = None
            
            return True
        return False
    
    def __str__(self):
        """
        返回棋盘的字符串表示（用于调试）
        
        Returns:
            str: 棋盘字符串
        """
        symbols = {0: '·', 1: '●', -1: '○'}
        result = []
        for row in self.board:
            result.append(' '.join(symbols[cell] for cell in row))
        return '\n'.join(result)
